﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using YArchitech.Revit;

namespace HYFloorPipeModule
{
	public class YXFloorPipeManager
	{
		public YXFloorPipeManager(List<XYZ> pts, DrawYxFloorPipeData drYxFloorPData)
		{
			this.ptBoundPionts = pts;
			this.drawYxFpdata = drYxFloorPData;
			this.ClearData();
		}

		public YXFloorPipeManager(List<MixPair> boundings, DrawYxFloorPipeData drYxFloorPData)
		{
			this.drawYxFpdata = drYxFloorPData;
			this.ClearData();
			this.boundingMps = new List<MixPair>();
			foreach (MixPair item in boundings)
			{
				this.boundingMps.Add(item);
			}
		}

		private void ClearData()
		{
			this.lstMpIn = this.InitLst<MixPair>(this.lstMpIn);
			this.lstMpOut = this.InitLst<MixPair>(this.lstMpOut);
			this.allCurveIn = this.InitLst<Curve>(this.allCurveIn);
			this.allCurveOut = this.InitLst<Curve>(this.allCurveOut);
		}

		private List<T> InitLst<T>(List<T> list)
		{
			list = (list ?? new List<T>());
			list.Clear();
			return list;
		}

		public bool Draw()
		{
			bool result = true;
			int isDouble = this.drawYxFpdata.IsDouble;
			if (isDouble != 0)
			{
				if (isDouble == 1)
				{
					result = this.DrawFloorPipe_Double();
					result = this.Connect_Double();
				}
			}
			else
			{
				result = this.DrawFloorPipe_Single();
				result = this.Connect_Single();
			}
			return result;
		}

		private bool DrawFloorPipe_Double()
		{
			List<MixPair> boundingMixPairs = null;
			if (this.boundingMps != null)
			{
				boundingMixPairs = (from boundingMp in this.boundingMps
				select new MixPair(boundingMp)).ToList<MixPair>();
			}
			YxPipesEdge yxPipesEdge = new YxPipesEdge(this.ptBoundPionts, this.drawYxFpdata);
			yxPipesEdge.SetIn(true);
			yxPipesEdge.CreatBound(this.boundingMps);
			yxPipesEdge.Offsetnew(this.drawYxFpdata.DisToWall);
			while (yxPipesEdge.CanContinueDraw())
			{
				yxPipesEdge.Offsetnew(this.drawYxFpdata.Dis * 2.0);
			}
			this.lstMpIn.AddRange(yxPipesEdge.allMp);
			this.DealLine(this.lstMpIn, yxPipesEdge.lstMixPair.Count);
			YxPipesEdge yxPipesEdge2 = new YxPipesEdge(this.ptBoundPionts, this.drawYxFpdata);
			yxPipesEdge2.SetIn(false);
			yxPipesEdge2.CreatBound(boundingMixPairs);
			yxPipesEdge2.Offsetnew(this.drawYxFpdata.DisToWall + this.drawYxFpdata.Dis);
			while (yxPipesEdge2.CanContinueDraw())
			{
				yxPipesEdge2.Offsetnew(this.drawYxFpdata.Dis * 2.0);
			}
			this.lstMpOut.AddRange(yxPipesEdge2.allMp);
			return this.DealLine(this.lstMpOut, yxPipesEdge2.lstMixPair.Count);
		}

		private bool Connect_Double()
		{
			if (this.lstMpIn.Count == 0 || this.lstMpOut.Count == 0)
			{
				return false;
			}
			this.lstMpIn.First<MixPair>().Retract(this.drawYxFpdata.Dis, 0.0);
			this.lstMpOut.First<MixPair>().Retract(this.drawYxFpdata.Dis, 0.0);
			MixPair mixPair = this.lstMpIn.Last<MixPair>();
			MixPair mixPair2 = this.lstMpOut.Last<MixPair>();
			if (mixPair.IsArc || mixPair2.IsArc)
			{
				if (mixPair.IsArc)
				{
					this.lstMpIn.Remove(mixPair);
					mixPair = this.lstMpIn.Last<MixPair>();
				}
				if (mixPair2.IsArc)
				{
					this.lstMpOut.Remove(mixPair2);
					mixPair2 = this.lstMpOut.Last<MixPair>();
				}
			}
			else if (mixPair.GetLength() > mixPair2.GetLength())
			{
				mixPair.Retract(0.0, 2.0 * this.drawYxFpdata.Dis);
				mixPair2.Retract(0.0, this.drawYxFpdata.Dis);
			}
			else
			{
				mixPair.Retract(0.0, this.drawYxFpdata.Dis);
				mixPair2.Retract(0.0, 2.0 * this.drawYxFpdata.Dis);
			}
			MixPair mixPair3 = new MixPair(mixPair.End, mixPair2.End, mixPair.IsIn);
			this.lstMpIn.Add(mixPair3);
			double num = 0.0;
			if (mixPair.IsParallel(mixPair2))
			{
				num = mixPair.DistanceTo(mixPair2);
			}
			this.MakeArcConnect(mixPair, mixPair3, 0.5 * num);
			mixPair3.DoExchange();
			this.MakeArcConnect(mixPair2, mixPair3, 0.5 * num);
			return true;
		}

		private bool DrawFloorPipe_Single()
		{
			YxPipesEdge yxPipesEdge = new YxPipesEdge(this.ptBoundPionts, this.drawYxFpdata);
			yxPipesEdge.SetIn(true);
			yxPipesEdge.CreatBound(this.boundingMps);
			yxPipesEdge.Offsetnew(this.drawYxFpdata.DisToWall);
			int num = (int)Math.Ceiling(this.GetMaxBoundingLength() / (this.drawYxFpdata.Dis * 1.5));
			while (yxPipesEdge.CanContinueDraw())
			{
				yxPipesEdge.Offsetnew(this.drawYxFpdata.Dis);
				num--;
			}
			this.firstDir = yxPipesEdge.firstDir;
			this.lstMpIn.AddRange(yxPipesEdge.allMp);
			return this.DealLine(this.lstMpIn, yxPipesEdge.lstMixPair.Count);
		}

		private bool Connect_Single()
		{
			if (this.lstMpIn.Count == 0)
			{
				return false;
			}
			MixPair mixPair = this.lstMpIn.Last<MixPair>();
			XYZ end = mixPair.End;
			MixPair mixPair2 = this.lstMpIn.First<MixPair>();
			mixPair2.Retract(this.drawYxFpdata.Dis, 0.0);
			XYZ xyz = mixPair2.Start;
			xyz += this.firstDir.Normalize() * 200.0 / 304.8;
			MixPair mixPair3 = new MixPair(end, xyz, mixPair.IsIn);
			this.MakeArcConnect(mixPair, mixPair3, 0.0);
			mixPair3.DoExchange();
			this.lstMpIn.Add(mixPair3);
			this.SingleLineDealAdd();
			return true;
		}

		private void SingleLineDealAdd()
		{
			List<MixPair> list = new List<MixPair>();
			for (int i = 0; i < this.lstMpIn.Count; i++)
			{
				list.Add(this.lstMpIn[i]);
				if (i < this.allArcPtIn.Count)
				{
					list.Add(new MixPair(this.allArcPtIn[i].Start, this.allArcPtIn[i].Mid, this.allArcPtIn[i].End, true));
				}
			}
			this.lstMpIn = null;
			this.allArcPtIn = null;
			this.lstMpIn = list;
		}

		private bool DealLine(List<MixPair> mps, int num = 0)
		{
			if (mps.Count == 0)
			{
				return false;
			}
			for (int i = 0; i < num; i++)
			{
				mps.Remove(mps.Last<MixPair>());
			}
			for (int j = 1; j < mps.Count - 1; j++)
			{
				if (this.JustMixPairMustDel(mps[j - 1], mps[j], mps[j + 1]))
				{
					mps.RemoveAt(j);
					j--;
				}
			}
			int count = mps.Count;
			for (int k = 0; k < count - 1; k++)
			{
				this.MakeArcConnect(mps[k], mps[k + 1], 0.0);
			}
			return true;
		}

		private void MakeArcConnect(MixPair curmp, MixPair nexmp, double dMPDis = 0.0)
		{
			if (this.allArcPtIn == null)
			{
				this.allArcPtIn = new List<ArcPtPair>();
			}
			if (this.allArcPtOut == null)
			{
				this.allArcPtOut = new List<ArcPtPair>();
			}
			Curve c = curmp.CreateCurve();
			Curve c2 = nexmp.CreateCurve();
			XYZ intersectionPoint = this.GetIntersectionPoint(c, c2);
			if (intersectionPoint == null)
			{
				return;
			}
			curmp.End = intersectionPoint;
			nexmp.Start = intersectionPoint;
			if (this.drawYxFpdata.DisRadius > 0.0 && !curmp.IsArc && !nexmp.IsArc)
			{
				ArcPtPair arcPtPair = new ArcPtPair();
				PointPair ppF = new PointPair(curmp.Start, curmp.End, curmp.IsIn, false);
				PointPair ppS = new PointPair(nexmp.Start, nexmp.End, nexmp.IsIn, false);
				double dRadius = (dMPDis != 0.0 && dMPDis < this.drawYxFpdata.DisRadius) ? (dMPDis - 0.0032808398950131233) : this.drawYxFpdata.DisRadius;
				arcPtPair.ReInitByTwoPerPair(ppF, ppS, dRadius, false);
				curmp.End = arcPtPair.Start;
				nexmp.Start = arcPtPair.End;
				if (arcPtPair.IsIn)
				{
					this.allArcPtIn.Add(arcPtPair);
					return;
				}
				this.allArcPtOut.Add(arcPtPair);
			}
		}

		private XYZ GetIntersectionPoint(Curve c1, Curve c2)
		{
			List<XYZ> list = new List<XYZ>();
			XYZ endPoint = c1.GetEndPoint(1);
			XYZ endPoint2 = c2.GetEndPoint(0);
			if (c1.IsBound)
			{
				c1.MakeUnbound();
			}
			if (c2.IsBound)
			{
				c2.MakeUnbound();
			}
			IntersectionResultArray intersectionResultArray = new IntersectionResultArray();
			SetComparisonResult setComparisonResult = c1.Intersect(c2, out intersectionResultArray);
			if (4 != (int)setComparisonResult && intersectionResultArray != null && !intersectionResultArray.IsEmpty)
			{
				for (int i = 0; i < intersectionResultArray.Size; i++)
				{
					list.Add(intersectionResultArray.get_Item(i).XYZPoint);
				}
			}
			if (list.Count == 0)
			{
				return null;
			}
			double num = list[0].DistanceTo(endPoint) + list[0].DistanceTo(endPoint2);
			XYZ result = list[0];
			foreach (XYZ xyz in list)
			{
				if (num > xyz.DistanceTo(endPoint) + xyz.DistanceTo(endPoint2))
				{
					num = xyz.DistanceTo(endPoint) + xyz.DistanceTo(endPoint2);
					result = xyz;
				}
			}
			return result;
		}

		private bool JustMixPairMustDel(MixPair preMp, MixPair curMp, MixPair nexMp)
		{
			XYZ intersectionPoint = this.GetIntersectionPoint(preMp.CreateCurve(), curMp.CreateCurve());
			XYZ intersectionPoint2 = this.GetIntersectionPoint(curMp.CreateCurve(), nexMp.CreateCurve());
			return intersectionPoint == null || intersectionPoint2 == null || (intersectionPoint2 - intersectionPoint).Normalize().IsAlmostEqualTo(-curMp.AsVector());
		}

		public void CreateCurve()
		{
			this.CreateCurve(this.lstMpIn);
			this.CreateCurve(this.lstMpOut);
			this.CreateCurve(this.allArcPtIn);
			this.CreateCurve(this.allArcPtOut);
		}

		private void CreateCurve(List<MixPair> mps)
		{
			if (mps == null || mps.Count == 0)
			{
				return;
			}
			foreach (MixPair mixPair in mps)
			{
				if (mixPair.IsIn)
				{
					this.allCurveIn.Add(mixPair.CreateCurve());
				}
				else
				{
					this.allCurveOut.Add(mixPair.CreateCurve());
				}
			}
		}

		private void CreateCurve(List<ArcPtPair> arcs)
		{
			if (arcs == null || arcs.Count == 0)
			{
				return;
			}
			foreach (ArcPtPair arcPtPair in arcs)
			{
				if (arcPtPair.IsIn)
				{
					try
					{
						this.allCurveIn.Add(arcPtPair.CreateArc());
						continue;
					}
					catch
					{
						continue;
					}
				}
				try
				{
					this.allCurveOut.Add(arcPtPair.CreateArc());
				}
				catch
				{
				}
			}
		}

		public double CalcTolLength()
		{
			double num = 0.0;
			foreach (Curve curve in this.allCurveIn)
			{
				num += curve.Length;
			}
			foreach (Curve curve2 in this.allCurveOut)
			{
				num += curve2.Length;
			}
			return num * 304.8 / 1000.0;
		}

		private double GetMaxBoundingLength()
		{
			double num = 0.0;
			if (this.ptBoundPionts != null)
			{
				for (int i = 0; i < this.ptBoundPionts.Count; i++)
				{
					if (i == this.ptBoundPionts.Count - 1)
					{
						num = ((this.ptBoundPionts[i].DistanceTo(this.ptBoundPionts[0]) > num) ? this.ptBoundPionts[i].DistanceTo(this.ptBoundPionts[0]) : num);
					}
					else
					{
						num = ((this.ptBoundPionts[i].DistanceTo(this.ptBoundPionts[i + 1]) > num) ? this.ptBoundPionts[i].DistanceTo(this.ptBoundPionts[i + 1]) : num);
					}
				}
			}
			if (this.boundingMps != null)
			{
				foreach (MixPair mixPair in this.boundingMps)
				{
					num = ((mixPair.GetLength() > num) ? mixPair.GetLength() : num);
				}
			}
			return num;
		}

		private List<XYZ> ptBoundPionts;

		private DrawYxFloorPipeData drawYxFpdata;

		private List<MixPair> lstMpIn;

		private List<MixPair> boundingMps;

		private List<MixPair> lstMpOut;

		public List<Curve> allCurveIn;

		public List<Curve> allCurveOut;

		private List<ArcPtPair> allArcPtIn;

		private List<ArcPtPair> allArcPtOut;

		private XYZ firstDir;
	}
}
